package com.example.chml7;

import java.text.DecimalFormat;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.PointF;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;

import com.androidplot.Plot;
import com.androidplot.xy.BoundaryMode;
import com.androidplot.xy.LineAndPointFormatter;
import com.androidplot.xy.SimpleXYSeries;
import com.androidplot.xy.XYPlot;

@SuppressLint("floatMath")
public class plotActivity extends Activity implements OnTouchListener {
    private XYPlot mySimpleXYPlot;
    private SimpleXYSeries[] series = null;
    private PointF minXY;
    private PointF maxXY;
    
    private double uReal[];
    private double UL[];
    private double UZ[];
    private double UM[];
    
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.zoom_plot);
        
        Intent intent = getIntent();
        uReal = intent.getDoubleArrayExtra("uReal");
        UL = intent.getDoubleArrayExtra("UL");
        UZ = intent.getDoubleArrayExtra("UZ");
        UM = intent.getDoubleArrayExtra("UM");
        
        boolean xConst = intent.getBooleanExtra("xConst", true);
        
        double x0 = intent.getDoubleExtra("x0", 0);
        double h = intent.getDoubleExtra("h", 0);
        
        mySimpleXYPlot = (XYPlot) findViewById(R.id.mySimpleXYPlot);
        mySimpleXYPlot.setOnTouchListener(this);
        mySimpleXYPlot.getGraphWidget().setTicksPerRangeLabel(2);
        mySimpleXYPlot.getGraphWidget().setTicksPerDomainLabel(2);
        mySimpleXYPlot.getGraphWidget().getBackgroundPaint().setColor(Color.TRANSPARENT);
        mySimpleXYPlot.getGraphWidget().setRangeValueFormat(
                new DecimalFormat("#####.##"));
        mySimpleXYPlot.getGraphWidget().setDomainValueFormat(
                new DecimalFormat("#####.##"));
        mySimpleXYPlot.getGraphWidget().setRangeLabelWidth(25);
        mySimpleXYPlot.setRangeLabel("");
        mySimpleXYPlot.setDomainLabel("");

        mySimpleXYPlot.setBorderStyle(Plot.BorderStyle.NONE, null, null);
        //mySimpleXYPlot.disableAllMarkup();
        series = new SimpleXYSeries[4];
        
        series[0] = new SimpleXYSeries("libman");
        series[1] = new SimpleXYSeries("zedel");
        series[2] = new SimpleXYSeries("mpi");
        series[3] = new SimpleXYSeries("real");
        
        for(int i = 0; i < UL.length; ++i)
        {
        	series[0].addLast(x0 + h*i, UL[i]);
        }
        
        for(int i = 0; i < UZ.length; ++i)
        {
        	series[1].addLast(x0 + h*i, UZ[i]);
        }
        
        for(int i = 0; i < UM.length; ++i)
        {
        	series[2].addLast(x0 + h*i, UM[i]);
        }
        
        for(int i = 0; i < uReal.length; ++i)
        {
        	series[3].addLast(x0 + h*i, uReal[i]);
        }

        if(UL.length > 2)
        {
        	Log.d("plot test", "UL");
        	mySimpleXYPlot.addSeries(series[0],
        			new LineAndPointFormatter(Color.rgb(100, 0, 0), null,
        					null, null));
        }
        
        if(UZ.length > 2)
        {
        	Log.d("plot test", "UZ");
        	mySimpleXYPlot.addSeries(series[1],
        			new LineAndPointFormatter(Color.rgb(0, 100, 0), null,
        					null, null));
        }
        
        if(UM.length > 2)
        {
        	Log.d("plot test", "UM");
        	mySimpleXYPlot.addSeries(series[2],
        			new LineAndPointFormatter(Color.rgb(100, 100, 100), null,
        					null, null));
        }
        
        if(uReal.length > 2)
        {
        	Log.d("plot test", "uReal");
        	mySimpleXYPlot.addSeries(series[3],
        			new LineAndPointFormatter(Color.rgb(0, 0, 100), null,
        					null, null));
        }
        mySimpleXYPlot.redraw();
        mySimpleXYPlot.calculateMinMaxVals();
        minXY = new PointF(mySimpleXYPlot.getCalculatedMinX().floatValue(),
                mySimpleXYPlot.getCalculatedMinY().floatValue());
        maxXY = new PointF(mySimpleXYPlot.getCalculatedMaxX().floatValue(),
                mySimpleXYPlot.getCalculatedMaxY().floatValue());
        Log.d("plot test", Float.toString(minXY.x) + " " + Float.toString(minXY.y));
        Log.d("plot test", Float.toString(maxXY.x) + " " + Float.toString(maxXY.y));
    }


    // Definition of the touch states
    static final int NONE = 0;
    static final int ONE_FINGER_DRAG = 1;
    static final int TWO_FINGERS_DRAG = 2;
    int mode = NONE;

    PointF firstFinger;
    float distBetweenFingers;
    boolean stopThread = false;

    @Override
    public boolean onTouch(View arg0, MotionEvent event) {
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN: // Start gesture
                firstFinger = new PointF(event.getX(), event.getY());
                mode = ONE_FINGER_DRAG;
                stopThread = true;
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_POINTER_UP:
                mode = NONE;
                break;
            case MotionEvent.ACTION_POINTER_DOWN: // second finger
                distBetweenFingers = spacing(event);
                // the distance check is done to avoid false alarms
                if (distBetweenFingers > 5f) {
                    mode = TWO_FINGERS_DRAG;
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (mode == ONE_FINGER_DRAG) {
                    PointF oldFirstFinger = firstFinger;
                    firstFinger = new PointF(event.getX(), event.getY());
                    scroll(oldFirstFinger.x - firstFinger.x);
                    mySimpleXYPlot.setDomainBoundaries(minXY.x, maxXY.x,
                            BoundaryMode.FIXED);
                    mySimpleXYPlot.redraw();

                } else if (mode == TWO_FINGERS_DRAG) {
                    float oldDist = distBetweenFingers;
                    distBetweenFingers = spacing(event);
                    zoom(oldDist / distBetweenFingers);
                    mySimpleXYPlot.setDomainBoundaries(minXY.x, maxXY.x,
                            BoundaryMode.FIXED);
                    mySimpleXYPlot.redraw();
                }
                break;
        }
        return true;
    }

    private void zoom(float scale) {
        float domainSpan = maxXY.x - minXY.x;
        float domainMidPoint = maxXY.x - domainSpan / 2.0f;
        float offset = domainSpan * scale / 2.0f;

        minXY.x = domainMidPoint - offset;
        maxXY.x = domainMidPoint + offset;

        //minXY.x = Math.min(minXY.x, series[3].getX(series[3].size() - 3)
        //        .floatValue());
        //maxXY.x = Math.max(maxXY.x, series[0].getX(1).floatValue());
        //clampToDomainBounds(domainSpan);
    }

    private void scroll(float pan) {
        float domainSpan = maxXY.x - minXY.x;
        float step = domainSpan / mySimpleXYPlot.getWidth();
        float offset = pan * step;
        minXY.x = minXY.x + offset;
        maxXY.x = maxXY.x + offset;
        //clampToDomainBounds(domainSpan);
    }

//    private void clampToDomainBounds(float domainSpan) {
//        float leftBoundary = series[0].getX(0).floatValue();
//        float rightBoundary = series[3].getX(series[3].size() - 1).floatValue();
//        // enforce left scroll boundary:
//        if (minXY.x < leftBoundary) {
//            minXY.x = leftBoundary;
//            maxXY.x = leftBoundary + domainSpan;
//        } else if (maxXY.x > series[3].getX(series[3].size() - 1).floatValue()) {
//            maxXY.x = rightBoundary;
//            minXY.x = rightBoundary - domainSpan;
//        }
//    }

    private float spacing(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return (float) Math.sqrt(x * x + y * y);
    }
}
